#include "RangePartitionMatcherDemo.h"

#include <iostream>
#include <ostream>
#include <algorithm>

bool ComparePartitions(RangePartition<int> rp1,RangePartition<int> rp2){
    return rp1.lowerBound < rp2.lowerBound;
}

void RangePartitionMatcherDemo::initial(std::vector<RangePartition<int> > partitions){
    std::cout << "RangePartitionMatcherDemo::initial()" << std::endl;
    // todo to be implemented

    for(auto& rp:partitions){
        if(rp.IsValidRange()){
            trueParitions.push_back(rp);
        }
    }

    sort(trueParitions.begin(),trueParitions.end(),ComparePartitions);

    for(auto& tp:trueParitions){
        std::cout << tp.lowerBound << " " << tp.upperBound << std::endl;
    }
}

std::vector<RangePartition<int> > RangePartitionMatcherDemo::getPartitions() const {
    std::cout << "RangePartitionMatcherDemo::getPartitions()" << std::endl;
    // todo to be implemented

    return trueParitions;
}

// std::optional<std::string> RangePartitionMatcherDemo::findPartitionByValue(const int &value) const {
//     std::cout << "RangePartitionMatcherDemo::findPartitionByValue()" << std::endl;
//     // todo to be implemented

//     for(auto& tp:trueParitions){
//         if(value >= tp.lowerBound && value < tp.upperBound){
//             return tp.name;
//         }
//     }

//     return std::nullopt;
// }

std::string RangePartitionMatcherDemo::findPartitionByValue(const int &value) const {
    std::cout << "RangePartitionMatcherDemo::findPartitionByValue()" << std::endl;
    // todo to be implemented

    //先排除不存在的情况
    if(value < trueParitions[0].lowerBound || value >= trueParitions.back().upperBound){
        return "InValid Range!";
    }else{
        //二分查找
        return BinSearch(value);
    }


    // for(auto& tp:trueParitions){
    //     if(value >= tp.lowerBound && value < tp.upperBound){
    //         return tp.name;
    //     }
    // }

    return "InValid Range!";
}

std::vector<std::string> RangePartitionMatcherDemo::findPartitionByRange(
    const int &rangeStart, const int &rangeEnd) const {
    std::cout << "RangePartitionMatcherDemo::findPartitionByRange()" << std::endl;
    // todo to be implemented

    std::vector<std::string> res;

    if(rangeStart >= rangeEnd ||
       rangeStart < trueParitions[0].lowerBound || rangeEnd >= trueParitions.back().upperBound){
        std::string err = "InValid Range!";
        // std::string err = "";
        res.push_back(err);
        return res;
    }else{
        res.push_back(BinSearch(rangeStart));
        res.push_back(BinSearch(rangeEnd));
    }



    // for(auto& tp:trueParitions){
    //     if((rangeStart >= tp.lowerBound && rangeStart < tp.upperBound) || 
    //         (rangeEnd >= tp.lowerBound && rangeEnd < tp.upperBound)){
    //             res.push_back(tp.name);
    //         }
    // }

    return res;
}


const std::string& RangePartitionMatcherDemo::BinSearch(const int& values) const{
    int left = 0;
    int right = trueParitions.size() - 1;

    while(left <= right){
        //防止整数溢出
        int mid = left + (right - left) / 2;
        if(values >= trueParitions[mid].upperBound){
            left = mid + 1;
        }else if(values < trueParitions[mid].lowerBound){
            right = mid - 1;
        }else{
            return trueParitions[mid].name;
        }
    }

    return nullptr;
}
